home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / minigl.lha / MiniGL / src / hclip.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-03  |  21.4 KB  |  997 lines

  1. /*
  2.  * $Id: hclip.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $
  3.  *
  4.  * $Date: 2000/04/07 19:44:51 $
  5.  * $Revision: 1.1.1.1 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15. static char rcsid[] = "$Id: hclip.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $";
  16.  
  17. #include "sysinc.h"
  18. #include <math.h>
  19.  
  20. #include <stdio.h> //remove this
  21.  
  22. #define CLIP_EPS (1e-7)
  23.  
  24. #define DUMP_VERTEX(vert) \
  25.  mykprintf("x:%6.3f y:%6.3f z:%6.3f w:%6.3f\nR:%6.3f G:%6.3f B:%6.3f A:%6.3f\nU:%6.3f V:%6.3f\noutcode=0x%X\n",\
  26.          (vert).bx, (vert).by, (vert).bz, (vert).bw,                                                                                      \
  27.          (vert).v.color.r, (vert).v.color.g, (vert).v.color.b, (vert).v.color.a,                                                          \
  28.          (vert).v.u, (vert).v.v, (vert).outcode)
  29.  
  30.  
  31. #define LERP(t,a,b) \
  32.     ( (a) + (float)t * ( (b) - (a) ) )
  33.  
  34.  
  35. #define x1 (a->bx)
  36. #define y1 (a->by)
  37. #define z1 (a->bz)
  38. #define w1 (a->bw)
  39.  
  40. #define x2 (b->bx)
  41. #define y2 (b->by)
  42. #define z2 (b->bz)
  43. #define w2 (b->bw)
  44.  
  45. #ifdef GLNDEBUG
  46. #define DEBUG_CLIP(name,code) code
  47. #else
  48. #define DEBUG_CLIP(name,code) \
  49.     mykprintf("%s: t=%f\n", #name, t);\
  50.     DUMP_VERTEX(*a); \
  51.     DUMP_VERTEX(*b); \
  52.     code             \
  53.     DUMP_VERTEX(*r);
  54. #endif
  55.  
  56.  
  57. //multitexturing with virtual units:(real unit0 + 1 virt)
  58.  
  59. /*
  60. Units are managed so unit0 is always first in line.
  61. Texture2D_State[1] is only set if there is any active units other than unit 0
  62.  
  63. If more than 1 hardware unit is present, the number of active virtual units should be reduced by 1. HW units should probably be implemented in a different manner.
  64. */
  65.  
  66.  
  67. static void hc_ClipWZero(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  68. {
  69.     float w;
  70.     ULONG outcode;
  71.  
  72.  
  73.     float t = (CLIP_EPS-w1)/(w2-w1);
  74.     r->bx = LERP(t,a->bx, b->bx);
  75.     r->by = LERP(t,a->by, b->by);
  76.     r->bz = LERP(t,a->bz, b->bz);
  77.     r->bw = CLIP_EPS;
  78.     if(shading == GL_SMOOTH)
  79.     {
  80.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  81.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  82.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  83.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  84.     }
  85.     r->v.u = LERP(t,a->v.u, b->v.u);
  86.     r->v.v = LERP(t,a->v.v, b->v.v);
  87.  
  88.     if(mini_CurrentContext->Texture2D_State[1])
  89.     {
  90.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  91.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  92.     }
  93.  
  94.     w = r->bw;
  95.     outcode = 0;
  96.  
  97.  
  98.     if (-w > r->bx)
  99.     {
  100.         outcode |= MGL_CLIP_LEFT;
  101.     }
  102.     else if (r->bx > w)
  103.     {
  104.         outcode |= MGL_CLIP_RIGHT;
  105.     }
  106.  
  107.     if (-w > r->by)
  108.     {
  109.         outcode |= MGL_CLIP_BOTTOM;
  110.     }
  111.     else if (r->by > w)
  112.     {
  113.         outcode |= MGL_CLIP_TOP;
  114.     }
  115.  
  116.     if (-w > r->bz)
  117.     {
  118.         outcode |= MGL_CLIP_BACK;
  119.     }
  120.     else if (r->bz > w)
  121.     {
  122.         outcode |= MGL_CLIP_FRONT;
  123.     }
  124.  
  125.     r->outcode = outcode;
  126.  
  127.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  128.     {
  129.     if (a->q == 1.0 && b->q == 1.0)
  130.         r->q = 1.0;
  131.     else
  132.         r->q = CLIP_EPS;
  133.     }
  134. }
  135.  
  136. static void hc_ClipLeft(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  137. {
  138.     float w;
  139.     ULONG outcode;
  140.     
  141.  
  142.     float t = (w1+x1)/((w1+x1)-(w2+x2));
  143.     r->by = LERP(t,a->by, b->by);
  144.     r->bz = LERP(t,a->bz, b->bz);
  145.     r->bw = LERP(t,a->bw, b->bw);
  146.     r->bx = -r->bw;
  147.     if(shading == GL_SMOOTH)
  148.     {
  149.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  150.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  151.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  152.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  153.     }
  154.     r->v.u = LERP(t,a->v.u, b->v.u);
  155.     r->v.v = LERP(t,a->v.v, b->v.v);
  156.  
  157.     if(mini_CurrentContext->Texture2D_State[1])
  158.     {
  159.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  160.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  161.     }
  162.  
  163.     w = r->bw;
  164.     outcode = 0;
  165.  
  166. /*
  167.     if (r->bw < CLIP_EPS )
  168.     {
  169.         outcode |= MGL_CLIP_NEGW;
  170.     }
  171. */
  172.  
  173.     if (-w > r->by)
  174.     {
  175.         outcode |= MGL_CLIP_BOTTOM;
  176.     }
  177.     else if (r->by > w)
  178.     {
  179.         outcode |= MGL_CLIP_TOP;
  180.     }
  181.  
  182.     if (-w > r->bz)
  183.     {
  184.         outcode |= MGL_CLIP_BACK;
  185.     }
  186.     else if (r->bz > w)
  187.     {
  188.         outcode |= MGL_CLIP_FRONT;
  189.     }
  190.  
  191.     r->outcode = outcode;
  192.  
  193.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  194.     {
  195.         r->q = LERP(t, a->q, b->q);
  196.     }
  197. }
  198.  
  199. static void hc_ClipRight(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  200. {
  201.     float w;
  202.     ULONG outcode;
  203.     
  204.  
  205.     float t = (w1-x1)/((w1-x1)-(w2-x2));
  206.     r->by = LERP(t,a->by, b->by);
  207.     r->bz = LERP(t,a->bz, b->bz);
  208.     r->bw = LERP(t,a->bw, b->bw);
  209.     r->bx = r->bw;
  210.     if(shading == GL_SMOOTH)
  211.     {
  212.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  213.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  214.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  215.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  216.     }
  217.     r->v.u = LERP(t,a->v.u, b->v.u);
  218.     r->v.v = LERP(t,a->v.v, b->v.v);
  219.  
  220.     if(mini_CurrentContext->Texture2D_State[1])
  221.     {
  222.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  223.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  224.     }
  225.  
  226.     w = r->bw;
  227.     outcode = 0;
  228.  
  229. /*
  230.     if (r->bw < CLIP_EPS )
  231.     {
  232.         outcode |= MGL_CLIP_NEGW;
  233.     }
  234. */
  235.  
  236.     if (-w > r->by)
  237.     {
  238.         outcode |= MGL_CLIP_BOTTOM;
  239.     }
  240.     else if (r->by > w)
  241.     {
  242.         outcode |= MGL_CLIP_TOP;
  243.     }
  244.  
  245.     if (-w > r->bz)
  246.     {
  247.         outcode |= MGL_CLIP_BACK;
  248.     }
  249.     else if (r->bz > w)
  250.     {
  251.         outcode |= MGL_CLIP_FRONT;
  252.     }
  253.  
  254.     r->outcode = outcode;
  255.  
  256.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  257.     {
  258.         r->q = LERP(t, a->q, b->q);
  259.     }
  260. }
  261.  
  262. static void hc_ClipFront(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  263. {
  264.     float w;
  265.     ULONG outcode;
  266.  
  267.  
  268.     float t = (w1-z1)/((w1-z1)-(w2-z2));
  269.     r->bx = LERP(t,a->bx, b->bx);
  270.     r->by = LERP(t,a->by, b->by);
  271.     r->bw = LERP(t,a->bw, b->bw);
  272.     r->bz = r->bw;
  273.     if(shading == GL_SMOOTH)
  274.     {
  275.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  276.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  277.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  278.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  279.     }
  280.     r->v.u = LERP(t,a->v.u, b->v.u);
  281.     r->v.v = LERP(t,a->v.v, b->v.v);
  282.  
  283.     if(mini_CurrentContext->Texture2D_State[1])
  284.     {
  285.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  286.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  287.     }
  288.  
  289.     w = r->bw;
  290.     outcode = 0;
  291.  
  292. /*
  293.     if (r->bw < CLIP_EPS )
  294.     {
  295.         outcode |= MGL_CLIP_NEGW;
  296.     }
  297.  
  298.     if (-w > r->bx)
  299.     {
  300.         outcode |= MGL_CLIP_LEFT;
  301.     }
  302.     else if (r->bx > w)
  303.     {
  304.         outcode |= MGL_CLIP_RIGHT;
  305.     }
  306. */
  307.     if (-w > r->by)
  308.     {
  309.         outcode |= MGL_CLIP_BOTTOM;
  310.     }
  311.     else if (r->by > w)
  312.     {
  313.         outcode |= MGL_CLIP_TOP;
  314.     }
  315.  
  316.     r->outcode = outcode;
  317.  
  318.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  319.     {
  320.         r->q = LERP(t, a->q, b->q);
  321.     }
  322. }
  323.  
  324. static void hc_ClipBack(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  325. {
  326.     float w;
  327.     ULONG outcode;
  328.  
  329.  
  330.     float t = (w1+z1)/((w1+z1)-(w2+z2));
  331.     r->bx = LERP(t,a->bx, b->bx);
  332.     r->by = LERP(t,a->by, b->by);
  333.     r->bw = LERP(t,a->bw, b->bw);
  334.     r->bz = -r->bw;
  335.     if(shading == GL_SMOOTH)
  336.     {
  337.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  338.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  339.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  340.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  341.     }
  342.     r->v.u = LERP(t,a->v.u, b->v.u);
  343.     r->v.v = LERP(t,a->v.v, b->v.v);
  344.  
  345.     if(mini_CurrentContext->Texture2D_State[1])
  346.     {
  347.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  348.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  349.     }
  350.  
  351.     w = r->bw;
  352.     outcode = 0;
  353.  
  354. /*
  355.     if (r->bw < CLIP_EPS )
  356.     {
  357.         outcode |= MGL_CLIP_NEGW;
  358.     }
  359.  
  360.     if (-w > r->bx)
  361.     {
  362.         outcode |= MGL_CLIP_LEFT;
  363.     }
  364.     else if (r->bx > w)
  365.     {
  366.         outcode |= MGL_CLIP_RIGHT;
  367.     }
  368. */
  369.     if (-w > r->by)
  370.     {
  371.         outcode |= MGL_CLIP_BOTTOM;
  372.     }
  373.     else if (r->by > w)
  374.     {
  375.         outcode |= MGL_CLIP_TOP;
  376.     }
  377.  
  378.     r->outcode = outcode;
  379.  
  380.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  381.     {
  382.         r->q = LERP(t, a->q, b->q);
  383.     }
  384. }
  385.  
  386. static void hc_ClipTop(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  387. {
  388.     float w;
  389.     ULONG outcode;
  390.  
  391.  
  392.     float t = (w1-y1)/((w1-y1)-(w2-y2));
  393.     r->bx = LERP(t,a->bx, b->bx);
  394.     r->bz = LERP(t,a->bz, b->bz);
  395.     r->bw = LERP(t,a->bw, b->bw);
  396.     r->by = r->bw;
  397.     if(shading == GL_SMOOTH)
  398.     {
  399.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  400.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  401.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  402.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  403.     }
  404.     r->v.u = LERP(t,a->v.u, b->v.u);
  405.     r->v.v = LERP(t,a->v.v, b->v.v);
  406.  
  407.     if(mini_CurrentContext->Texture2D_State[1])
  408.     {
  409.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  410.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  411.     }
  412.  
  413. /*
  414. Surgeon: this is always the 2nd last routine called, so here is no need to recode since a top-code means that there can be no bottom-code - we can safely set the outcode of the clipped vert to 0
  415. */
  416. #if 1
  417.     r->outcode = 0;
  418. #else
  419.     w = r->bw;
  420.     outcode = 0;
  421.  
  422.     if (r->bw < CLIP_EPS )
  423.     {
  424.         outcode |= MGL_CLIP_NEGW;
  425.     }
  426.  
  427.     if (-w > r->bx)
  428.     {
  429.         outcode |= MGL_CLIP_LEFT;
  430.     }
  431.     else if (r->bx > w)
  432.     {
  433.         outcode |= MGL_CLIP_RIGHT;
  434.     }
  435.  
  436.     if (-w > r->bz)
  437.     {
  438.         outcode |= MGL_CLIP_BACK;
  439.     }
  440.     else if (r->bz > w)
  441.     {
  442.         outcode |= MGL_CLIP_FRONT;
  443.     }
  444.  
  445.     r->outcode = outcode;
  446. #endif
  447.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  448.     {
  449.         r->q = LERP(t, a->q, b->q);
  450.     }
  451. }
  452.  
  453. static void hc_ClipBottom(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading)
  454. {
  455.     float w;
  456.     ULONG outcode;
  457.  
  458.  
  459.     float t = (w1+y1)/((w1+y1)-(w2+y2));
  460.     r->bx = LERP(t,a->bx, b->bx);
  461.     r->bz = LERP(t,a->bz, b->bz);
  462.     r->bw = LERP(t,a->bw, b->bw);
  463.     r->by = -r->bw;
  464.     if(shading == GL_SMOOTH)
  465.     {
  466.     r->v.color.a = LERP(t,a->v.color.a, b->v.color.a);
  467.     r->v.color.r = LERP(t,a->v.color.r, b->v.color.r);
  468.     r->v.color.g = LERP(t,a->v.color.g, b->v.color.g);
  469.     r->v.color.b = LERP(t,a->v.color.b, b->v.color.b);
  470.     }
  471.     r->v.u = LERP(t,a->v.u, b->v.u);
  472.     r->v.v = LERP(t,a->v.v, b->v.v);
  473.  
  474.     if(mini_CurrentContext->Texture2D_State[1])
  475.     {
  476.         r->tcoord.s = LERP(t,a->tcoord.s, b->tcoord.s);
  477.         r->tcoord.t = LERP(t,a->tcoord.t, b->tcoord.t);
  478.     }
  479.  
  480. /*
  481. Surgeon: this is always the last routine called, so here is no need to recode - we can safely set the outcode of the clipped vert to 0
  482. */
  483. #if 1
  484.     r->outcode = 0;
  485. #else
  486.     w = r->bw;
  487.     outcode = 0;
  488.  
  489.     if (r->bw < CLIP_EPS )
  490.     {
  491.         outcode |= MGL_CLIP_NEGW;
  492.     }
  493.  
  494.     if (-w > r->bx)
  495.     {
  496.         outcode |= MGL_CLIP_LEFT;
  497.     }
  498.     else if (r->bx > w)
  499.     {
  500.         outcode |= MGL_CLIP_RIGHT;
  501.     }
  502.  
  503.     if (-w > r->bz)
  504.     {
  505.         outcode |= MGL_CLIP_BACK;
  506.     }
  507.     else if (r->bz > w)
  508.     {
  509.         outcode |= MGL_CLIP_FRONT;
  510.     }
  511.  
  512.     r->outcode = outcode;
  513. #endif
  514.     if(mini_CurrentContext->CurrentTexQValid == GL_TRUE)
  515.     {
  516.         r->q = LERP(t, a->q, b->q);
  517.     }
  518. }
  519.  
  520.  
  521.  
  522. #undef x1
  523. #undef y1
  524. #undef z1
  525. #undef w1
  526. #undef x2
  527. #undef y2
  528. #undef z2
  529. #undef w2
  530.  
  531. GLboolean hc_DecideFrontface(GLcontext context, MGLVertex *a, MGLVertex *b, MGLVertex *c)
  532. {
  533.     GLboolean front;
  534.     float a1,a2,b1,b2,r;
  535.     float aw,bw,cw;
  536.  
  537.     aw = 1.0 / a->bw;
  538.     bw = 1.0 / b->bw;
  539.     cw = 1.0 / c->bw;
  540.  
  541.     a1 = a->bx*aw - b->bx*bw;
  542.     a2 = a->by*aw - b->by*bw;
  543.     b1 = c->bx*cw - b->bx*bw;
  544.     b2 = c->by*cw - b->by*bw;
  545.  
  546.     #define EPSILON (1e-5)
  547.  
  548. #if 0
  549.  
  550. /*
  551. Surgeon: BUGFIX
  552. These expressions test the length of the triangle-sides in 3D space and is in essence a simple areatest - it should return GL_FALSE instead of GL_TRUE
  553. */
  554.  
  555.     if (fabs(a1) < EPSILON && fabs(a2) < EPSILON)
  556.     {
  557.         return GL_TRUE;
  558.     }
  559.  
  560.     if (fabs(b1) < EPSILON && fabs(b2) < EPSILON)
  561.     {
  562.         return GL_TRUE;
  563.     }
  564. #else
  565.  
  566. #if 0
  567. //this test catches less than 1 in 1000 triangles so we disable it anyway
  568.  
  569.     if (fabs(a1) < EPSILON && fabs(a2) < EPSILON)
  570.     {
  571.         return GL_FALSE;
  572.     }
  573.  
  574.     if (fabs(b1) < EPSILON && fabs(b2) < EPSILON)
  575.     {
  576.         return GL_FALSE;
  577.     }
  578. #endif
  579.  
  580. #endif
  581.  
  582.     r  = a1*b2-a2*b1;
  583.  
  584.     if ((r < 0.0 && context->CurrentCullSign < 0) ||
  585.         (r > 0.0 && context->CurrentCullSign > 0))
  586.     {
  587.         return GL_FALSE;
  588.     }
  589.     else
  590.     {
  591.         return GL_TRUE;
  592.     }
  593. }
  594.  
  595.  
  596. void GLFrontFace(GLcontext context, GLenum mode)
  597. {
  598.     int facing;
  599.     GLint sign;
  600.  
  601.     if (mode == GL_CW || mode == GL_CCW)
  602.     {
  603.        context->CurrentFrontFace = mode;
  604.  
  605.     //Surgeon -->
  606.  
  607.        facing = (int)context->CurrentCullFace;
  608.  
  609.        switch(facing)
  610.        {
  611.         case GL_BACK:
  612.             sign = 1;
  613.             break;
  614.         case GL_FRONT:
  615.             sign = -1;
  616.             break;
  617.         default:
  618.             sign = 0;
  619.             break;
  620.        }
  621.     
  622.        if(mode == GL_CW)
  623.        {
  624.         sign = -sign;
  625.        }
  626.  
  627.        context->CurrentCullSign = sign;
  628.  
  629.     //Surgeon <--
  630.  
  631.     }
  632.     else
  633.     {
  634.         GLFlagError(context, 1, GL_INVALID_ENUM);
  635.     }
  636. }
  637.  
  638. void GLCullFace(GLcontext context, GLenum mode)
  639. {
  640.     GLint sign;
  641.  
  642.     if (mode == GL_FRONT || mode == GL_FRONT_AND_BACK || mode == GL_BACK)
  643.     {
  644.     context->CurrentCullFace = mode;
  645.  
  646.     //Surgeon -->
  647.  
  648.        switch ((int)mode)
  649.        {
  650.         case GL_BACK:
  651.             sign = 1;
  652.             break;
  653.         case GL_FRONT:
  654.             sign = -1;
  655.             break;
  656.         default:
  657.             sign = 0;
  658.             break;
  659.        }
  660.  
  661.        if(context->CurrentFrontFace == GL_CW)
  662.        {
  663.         sign = -sign;
  664.        }
  665.  
  666.     context->CurrentCullSign = sign;
  667.  
  668.     //Surgeon <--
  669.     }
  670.     else
  671.     {
  672.         GLFlagError(context, 1, GL_INVALID_ENUM);
  673.     }
  674. }
  675.  
  676. /*
  677. ** Complicated clipping macro stuff.
  678. */
  679.  
  680. #define VERTP(i) &(context->VertexBuffer[a->verts[i]])
  681. #define VERT(i) ( context->VertexBuffer[a->verts[i]] )
  682.  
  683. #define OLD_POLYSWAP \
  684.     if (b->numverts == 0) return; \
  685.     temp=a; a=b; b=temp; \
  686.  
  687. #define POLYSWAP \
  688.     if (b->numverts == 0) {out->numverts = 0;return;} \
  689.     temp=a; a=b; b=temp; \
  690.  
  691. #define OLD_DOCLIP(edge, routine)                                           \
  692.     if (or_codes & edge)                                                 \
  693.     {                                                                     \
  694.         b->numverts = 0;                                                   \
  695.         prev = a->numverts-1;                                               \
  696.     i=0;    do                 \
  697.         {                                                                     \
  698.             /* Case 1 and 4*/                                                  \
  699.             if (!(VERT(prev).outcode & edge))                                   \
  700.             {                                                                    \
  701.                 b->verts[b->numverts] = a->verts[prev];                           \
  702.                 b->numverts++;                                                     \
  703.             }                                                                       \
  704.             /* Case 3 and 4 */                                                       \
  705.             if ((VERT(prev).outcode ^ VERT(i).outcode) & edge)                        \
  706.             {                                                                          \
  707.                 hc_##routine (VERTP(prev), VERTP(i), &(context->VertexBuffer[free]), (const GLenum)context->ShadeModel);   \
  708.                 b->verts[b->numverts]=free++;                                            \
  709.                 b->numverts++;                                                            \
  710.             }                                                                              \
  711.             prev = i;                                                                       \
  712.         } while (++i < a->numverts); \
  713.         OLD_POLYSWAP                 \
  714.     }                                                      
  715.  
  716. #define DOCLIP(edge, routine)                                           \
  717.     if (or_codes & edge)                                                 \
  718.     {                                                                     \
  719.         b->numverts = 0;                                                   \
  720.         prev = a->numverts-1;                                               \
  721.     i=0; do    {                                                                          \
  722.             /* Case 1 and 4*/                                                  \
  723.             if (!(VERT(prev).outcode & edge))                                   \
  724.             {                                                                    \
  725.                 b->verts[b->numverts] = a->verts[prev];                           \
  726.                 b->numverts++;                                                     \
  727.             }                                                                       \
  728.             /* Case 3 and 4 */                                                       \
  729.             if ((VERT(prev).outcode ^ VERT(i).outcode) & edge)                        \
  730.             {                                                                                  \
  731.                 hc_##routine (VERTP(prev), VERTP(i), &(context->VertexBuffer[free]), (const GLenum)context->ShadeModel);                \
  732.                 b->verts[b->numverts]=free++;                                              \
  733.                 b->numverts++;                                                             \
  734.             }                     \
  735.             prev = i;             \
  736.         }  while (++i < a->numverts); \
  737.         POLYSWAP                      \
  738.     }                                                      
  739.  
  740. #ifndef GLNDEBUG
  741. void hc_DumpPolygon(GLcontext context, MGLPolygon *poly, char *string, int clipcode)
  742. {
  743.     int i;
  744.     mykprintf("--- %s (0x%X) -- (%d vertices)\n", string,clipcode, poly->numverts);
  745.     for (i=0; i<poly->numverts; i++)
  746.     {
  747.         DUMP_VERTEX(context->VertexBuffer[poly->verts[i]]);
  748.     }
  749.     mykprintf("-------------------------\n");
  750. }
  751.  
  752. #define CLIPDBG(string,code) \
  753.     hc_DumpPolygon(context,a,#string,code);
  754.  
  755. #else
  756.  
  757. #define CLIPDBG(string,code)
  758.  
  759. #endif
  760.  
  761.  
  762. void hc_ClipAndDrawPoly(GLcontext context, MGLPolygon *poly, ULONG or_codes)
  763. {
  764.     /*
  765.     ** Sutherland-Hodgeman clipping algorithm (almost)
  766.     **
  767.     ** This clipping algorithm sucessively clips against each of the six
  768.     ** clipping planes (additional client-defined clipping planes would
  769.     ** be possible, those would be added to the back of this).
  770.     ** Vertices are copied from a to b and swapped at the end.
  771.     ** Output occurs within the clipping region:
  772.     **
  773.     **                | b
  774.     **               i|/|
  775.     **               /| |
  776.     **              / | |c
  777.     **            a/  |/
  778.     **             | /|j
  779.     **             |/ |
  780.     **            d/  |
  781.     **                |clip plane
  782.     **
  783.     ** In the above figure, the algorithm first consideres edge d-a. Since it
  784.     ** does not cross the clipping plane, it outputs d and proceeds to edge
  785.     ** a-b. Since it crosses, it outputs a, calculates intersection i and outputs it.
  786.     ** No output occurs while b-c is considered, since it lies outside the frustum
  787.     ** and does not cross it. Finally, edge c-d yields output j.
  788.     **
  789.     ** The result is d-a-i-j
  790.     **
  791.     ** Classification of edges are divided into four cases:
  792.     ** Case 1: Edge is completely inside -> two vertices
  793.     ** Case 2: Edge is completely outside -> no output
  794.     ** Case 3: Edge enters the frustum -> one output
  795.     ** Case 4: Edge leaves frustum -> two outputs
  796.     **
  797.     ** At any stage, if the output polygon has zero vertices, return immediately.
  798.     */
  799.  
  800.     MGLPolygon output;
  801.     MGLPolygon *a, *b, *temp;
  802.     int i,j;
  803.     int prev;
  804.     int free = context->VertexBufferPointer;
  805.     GLboolean flag;
  806.     ULONG original_or_codes = or_codes;
  807.  
  808.     a = poly; b=&output;
  809.  
  810.     CLIPDBG(ClipWZero, MGL_CLIP_NEGW)
  811.     OLD_DOCLIP(MGL_CLIP_NEGW, ClipWZero);
  812.  
  813. // Surgeon: conditioned by macro execution
  814.       if(or_codes & MGL_CLIP_NEGW)
  815.     {
  816.     j = 0;
  817.         do
  818.         {
  819.         or_codes |= context->VertexBuffer[a->verts[j]].outcode;
  820.         j++;
  821.         } while (j < a->numverts);
  822.     }
  823.  
  824.     CLIPDBG(ClipLeft, MGL_CLIP_LEFT)
  825.     OLD_DOCLIP(MGL_CLIP_LEFT, ClipLeft)
  826.  
  827.     CLIPDBG(ClipRight, MGL_CLIP_RIGHT)
  828.     OLD_DOCLIP(MGL_CLIP_RIGHT, ClipRight)
  829.  
  830.     CLIPDBG(ClipFront, MGL_CLIP_FRONT)
  831.     OLD_DOCLIP(MGL_CLIP_FRONT, ClipFront)
  832.  
  833.     CLIPDBG(ClipBack, MGL_CLIP_BACK)
  834.     OLD_DOCLIP(MGL_CLIP_BACK, ClipBack)
  835.  
  836.     CLIPDBG(ClipTop, MGL_CLIP_TOP)
  837.     OLD_DOCLIP(MGL_CLIP_TOP, ClipTop)
  838.  
  839.     CLIPDBG(ClipBottom, MGL_CLIP_BOTTOM)
  840.     OLD_DOCLIP(MGL_CLIP_BOTTOM, ClipBottom)
  841.  
  842.     CLIPDBG(Final,0)
  843.  
  844.     // If we get here, there are vertices left...
  845.     dh_DrawPoly(context, a);
  846. }
  847.  
  848.  
  849. void hc_ClipAndDrawLine(GLcontext context, MGLPolygon *poly, ULONG or_codes)
  850. {
  851.     MGLPolygon output;
  852.     MGLPolygon *a, *b, *temp;
  853.     int i,j;
  854.     int prev;
  855.     int free = context->VertexBufferPointer;
  856.     GLboolean flag;
  857.     ULONG original_or_codes = or_codes;
  858.  
  859.     a = poly; b=&output;
  860.  
  861.     OLD_DOCLIP(MGL_CLIP_NEGW, ClipWZero);
  862.  
  863. // Surgeon: conditioned by macro execution
  864.       if(or_codes & MGL_CLIP_NEGW)
  865.     {
  866.     j = 0;
  867.         do
  868.         {
  869.         or_codes |= context->VertexBuffer[a->verts[j]].outcode;
  870.         j++;
  871.         } while (j < a->numverts);
  872.     }
  873.  
  874.     OLD_DOCLIP(MGL_CLIP_LEFT, ClipLeft)
  875.     OLD_DOCLIP(MGL_CLIP_RIGHT, ClipRight)
  876.     OLD_DOCLIP(MGL_CLIP_FRONT, ClipFront)
  877.     OLD_DOCLIP(MGL_CLIP_BACK, ClipBack)
  878.     OLD_DOCLIP(MGL_CLIP_TOP, ClipTop)
  879.     OLD_DOCLIP(MGL_CLIP_BOTTOM, ClipBottom)
  880.  
  881.     dh_DrawLine(context,a);
  882. }
  883.  
  884.  
  885. //buffering: 
  886.  
  887. void hc_ClipPoly(GLcontext context, MGLPolygon *poly, PolyBuffer *out, int clipstart, ULONG or_codes)
  888. {
  889.     MGLPolygon output;
  890.     MGLPolygon *a, *b, *temp;
  891.     int i,j;
  892.     int prev;
  893.     int free = clipstart;
  894.     ULONG original_or_codes = or_codes;
  895.  
  896.     a = poly; b=&output;
  897.  
  898.     CLIPDBG(ClipWZero, MGL_CLIP_NEGW)
  899.     DOCLIP(MGL_CLIP_NEGW, ClipWZero);
  900.  
  901. // Surgeon: conditioned by macro execution
  902.       if(or_codes & MGL_CLIP_NEGW)
  903.     {
  904.     j = 0;
  905.         do
  906.         {
  907.         or_codes |= context->VertexBuffer[a->verts[j]].outcode;
  908.         j++;
  909.         } while (j < a->numverts);
  910.     }
  911.  
  912.     CLIPDBG(ClipLeft, MGL_CLIP_LEFT)
  913.     DOCLIP(MGL_CLIP_LEFT, ClipLeft)
  914.  
  915.     CLIPDBG(ClipRight, MGL_CLIP_RIGHT)
  916.     DOCLIP(MGL_CLIP_RIGHT, ClipRight)
  917.  
  918.     CLIPDBG(ClipFront, MGL_CLIP_FRONT)
  919.     DOCLIP(MGL_CLIP_FRONT, ClipFront)
  920.  
  921.     CLIPDBG(ClipBack, MGL_CLIP_BACK)
  922.     DOCLIP(MGL_CLIP_BACK, ClipBack)
  923.  
  924.     CLIPDBG(ClipTop, MGL_CLIP_TOP)
  925.     DOCLIP(MGL_CLIP_TOP, ClipTop)
  926.  
  927.     CLIPDBG(ClipBottom, MGL_CLIP_BOTTOM)
  928.     DOCLIP(MGL_CLIP_BOTTOM, ClipBottom)
  929.  
  930.     CLIPDBG(Final,0)
  931.  
  932.  
  933. //write buffer index
  934.     for(j=0; j<a->numverts; j++)
  935.         out->verts[j] = a->verts[j];
  936.  
  937.     out->numverts = a->numverts;
  938.     out->nextfree = free;
  939. }
  940.  
  941.  
  942. void hc_ClipPolyFF(GLcontext context, MGLPolygon *poly, ULONG or_codes)
  943. {
  944.     MGLPolygon *out;
  945.     MGLPolygon output;
  946.     MGLPolygon *a, *b, *temp;
  947.     int i,j;
  948.     int prev;
  949.     int free = context->VertexBufferPointer;
  950.  
  951.     a = poly; b=&output;
  952.     out = poly;
  953.  
  954.     CLIPDBG(ClipWZero, MGL_CLIP_NEGW)
  955.     DOCLIP(MGL_CLIP_NEGW, ClipWZero);
  956.  
  957. // Surgeon: conditioned by macro execution
  958.       if(or_codes & MGL_CLIP_NEGW)
  959.     {
  960.     j = 0;
  961.         do
  962.         {
  963.         or_codes |= context->VertexBuffer[a->verts[j]].outcode;
  964.         j++;
  965.         } while (j < a->numverts);
  966.     }
  967.  
  968.     CLIPDBG(ClipLeft, MGL_CLIP_LEFT)
  969.     DOCLIP(MGL_CLIP_LEFT, ClipLeft)
  970.  
  971.     CLIPDBG(ClipRight, MGL_CLIP_RIGHT)
  972.     DOCLIP(MGL_CLIP_RIGHT, ClipRight)
  973.  
  974.     CLIPDBG(ClipFront, MGL_CLIP_FRONT)
  975.     DOCLIP(MGL_CLIP_FRONT, ClipFront)
  976.  
  977.     CLIPDBG(ClipBack, MGL_CLIP_BACK)
  978.     DOCLIP(MGL_CLIP_BACK, ClipBack)
  979.  
  980.     CLIPDBG(ClipTop, MGL_CLIP_TOP)
  981.     DOCLIP(MGL_CLIP_TOP, ClipTop)
  982.  
  983.     CLIPDBG(ClipBottom, MGL_CLIP_BOTTOM)
  984.     DOCLIP(MGL_CLIP_BOTTOM, ClipBottom)
  985.  
  986.     CLIPDBG(Final,0)
  987.  
  988. //write buffer index
  989.     for(j=0; j<a->numverts; j++)
  990.         poly->verts[j] = a->verts[j];
  991.  
  992.     poly->numverts = a->numverts;
  993. }
  994.  
  995.  
  996.  
  997.